package com.freedom.sql.jdbc.response;

import java.io.UnsupportedEncodingException;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.freedom.sql.jdbc.netty.MyNioSocketChannel;
import com.freedom.sql.jdbc.utils.BufferAllocateUtils;
import com.freedom.sql.jdbc.utils.ByteUtils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.socket.SocketChannel;

public class ErrorPacket {
	@SuppressWarnings("unused")
	private static final Logger logger = LogManager.getLogger(ErrorPacket.class);
	private MyNioSocketChannel channel;
	private int packetSeq;
	private int errnoFlag;
	private String msg;
	private String sqlState;
	private boolean close;

	public ErrorPacket(boolean _close, SocketChannel c, int pSeq, int e, String m, String s) {
		close = _close;
		channel = (MyNioSocketChannel) c;
		packetSeq = pSeq;
		errnoFlag = e;
		msg = m;
		sqlState = s;
	}

	public void write() {
		// 1)packet length
		byte[] headerLen = null;
		// 2)packet number
		byte[] packetNumber = ByteUtils.writeInt(packetSeq, 1);
		// 3)error
		byte[] error = new byte[1];
		error[0] = (byte) 0xff;
		// 4) concrete error flag
		byte[] flag = ByteUtils.writeInt(errnoFlag, 2);
		// 5)marker
		byte[] marker = new byte[1];
		marker[0] = 0x23;
		// 6)sql state
		byte[] sqlStateByte = this.sqlState.getBytes();
		// 7)msg
		byte[] msgByte;
		if (null != channel.getCharset() && channel.getCharset().length() > 0) {
			try {
				msgByte = msg.getBytes(channel.getCharset());
			} catch (UnsupportedEncodingException e) {
				msgByte = msg.getBytes();
			}
		} else {
			msgByte = msg.getBytes();
		}
		int totalPacketLen = 0;
		{
			// totalPacketLen += packetNumber.length;
			totalPacketLen += error.length;
			totalPacketLen += flag.length;
			totalPacketLen += marker.length;
			totalPacketLen += sqlStateByte.length;
			totalPacketLen += msgByte.length;
			headerLen = ByteUtils.writeInt(totalPacketLen, 3);
		}
		// 构造最终的缓冲区,统一分配,方便后面切换
		ByteBuf finalBuf = BufferAllocateUtils.get(totalPacketLen + 4);
		finalBuf.writeBytes(headerLen);
		finalBuf.writeBytes(packetNumber);
		finalBuf.writeBytes(error);
		finalBuf.writeBytes(flag);
		finalBuf.writeBytes(marker);
		finalBuf.writeBytes(sqlStateByte);
		finalBuf.writeBytes(msgByte);
		// 最后才发送出去
		if (close) {// 确实关闭
			channel.writeAndFlush(finalBuf).addListener(ChannelFutureListener.CLOSE);
		} else {// 不关闭，交给client处理异常
			channel.writeAndFlush(finalBuf);
		}
	}
}
